﻿using System;
using System.Linq;
using System.Collections.Generic;
using TeamCommunitySolution.Domain.DataLayer.Venues;
using TeamCommunitySolution.Domain.Extensions;
using TeamCommunitySolution.Domain.DataLayer.PlayerMetrics;
using TeamCommunitySolution.Domain.DataLayer.Leagues;
using TeamCommunitySolution.Domain.DataLayer.TeamEvents;

namespace TeamCommunitySolution.Domain.DataLayer.Base
{
    [Serializable]
    public class SystemUser
    {
        /// <summary>
        /// Gets or sets the id.
        /// </summary>
        /// <value>The id of the instance.</value>
        public virtual string Id { get; set; }

        /// <summary>
        /// Gets or sets the email.
        /// </summary>
        /// <value>The email.</value>
        public virtual string Email { get; set; }

        /// <summary>
        /// Gets or sets the password.
        /// </summary>
        /// <value>The password.</value>
        public virtual string Password { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is approved.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is approved; otherwise, <c>false</c>.
        /// </value>
        public virtual bool IsApproved { get; set; }

        /// <summary>
        /// Gets or sets the last login date.
        /// </summary>
        /// <value>The last login date.</value>
        public virtual DateTime LastLoginDate { get; set; }

        /// <summary>
        /// Gets or sets the last password changed.
        /// </summary>
        /// <value>The last password changed.</value>
        public virtual DateTime LastPasswordChanged { get; set; }

        /// <summary>
        /// Gets or sets the creation date.
        /// </summary>
        /// <value>The creation date.</value>
        public virtual DateTime CreationDate { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is online.
        /// </summary>
        /// <value><c>true</c> if this instance is online; otherwise, <c>false</c>.</value>
        public virtual bool IsOnline { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is locked out.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is locked out; otherwise, <c>false</c>.
        /// </value>
        public virtual bool IsLockedOut { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is enabled.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is enabled; otherwise, <c>false</c>.
        /// </value>
        public virtual bool IsEnabled { get; set; }

        /// <summary>
        /// Gets or sets the first name.
        /// </summary>
        /// <value>The first name.</value>
        public virtual string FirstName { get; set; }

        /// <summary>
        /// Gets or sets the last name.
        /// </summary>
        /// <value>The last name.</value>
        public virtual string LastName { get; set; }

        /// <summary>
        /// Gets or sets the name of the nick.
        /// </summary>
        /// <value>The name of the nick.</value>
        public virtual string NickName { get; set; }

        /// <summary>
        /// Gets or sets the date of birth.
        /// </summary>
        /// <value>The date of birth.</value>
        public virtual DateTime DateOfBirth { get; set; }

        /// <summary>
        /// Gets or sets the user gender.
        /// </summary>
        /// <value>The user gender.</value>
        public virtual Gender UserGender { get; set; }

        /// <summary>
        /// Gets a value indicating whether this instance is valid.
        /// </summary>
        /// <value><c>true</c> if this instance is valid; otherwise, <c>false</c>.</value>
        public virtual bool IsValid
        {
            get
            {
                return this.GetRuleViolations().Count() == 0;
            }
        }

        #region# "Venues"

        /// <summary>
        /// Gets or sets the owner venue list.
        /// </summary>
        /// <value>The owner venue list.</value>
        public virtual IList<Venue> OwnerVenueList { get; set; }

        #endregion#

        #region "Messaging"

        /// <summary>
        /// Gets or sets the private message inbox.
        /// </summary>
        /// <value>The private message inbox.</value>
        public virtual IList<MessageInbox> PrivateMessageInbox { get; set; }

        /// <summary>
        /// Gets or sets the private message outbox.
        /// </summary>
        /// <value>The private message outbox.</value>
        public virtual IList<MessageOutbox> PrivateMessageOutbox { get; set; }

        #endregion

        #region "Teams"

        /// <summary>
        /// Gets or sets the team created list.
        /// </summary>
        /// <value>The team created list.</value>
        public virtual IList<Team> TeamCreatedList { get; set; }

        /// <summary>
        /// Gets or sets the member of team list.
        /// </summary>
        /// <value>The member of team list.</value>
        public virtual IList<Team> MemberOfTeamList { get; set; }

        /// <summary>
        /// Gets or sets the team request sent list.
        /// </summary>
        /// <value>The team request sent list.</value>
        public virtual IList<TeamInvite> TeamRequestSentList { get; set; }

        /// <summary>
        /// Gets or sets the team request received list.
        /// </summary>
        /// <value>The team request received list.</value>
        public virtual IList<TeamInvite> TeamRequestReceivedList { get; set; }

        /// <summary>
        /// Gets or sets the owner team event list.
        /// </summary>
        /// <value>The owner team event list.</value>
        public virtual IList<TeamEvent> OwnerTeamEventList { get; set; }

        #endregion

        #region "Metrics"

        public virtual IList<MetricContent> MetricList { get; set; }

        #endregion#

        #region "Leagues"

        public virtual IList<League> OwnerLeagueList { get; set; }

        #endregion#

        #region Extensions
        /// <summary>
        /// Gets the rule violations.
        /// </summary>
        /// <returns>Rule Violation</returns>
        public virtual IEnumerable<RuleViolation> GetRuleViolations()
        {
            if (string.IsNullOrEmpty(this.Email))
            {
                yield return new RuleViolation("Email required", "Email");
            }

            if (string.IsNullOrEmpty(this.FirstName))
            {
                yield return new RuleViolation("First name required", "FirstName");
            }

            if (string.IsNullOrEmpty(this.LastName))
            {
                yield return new RuleViolation("Last name required", "LastName");
            }

            yield break;
        }
        #endregion

        /// <summary>
        /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
        /// <returns>
        /// <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        /// <exception cref="T:System.NullReferenceException">
        /// The <paramref name="obj"/> parameter is null.
        /// </exception>
        public override bool Equals(object obj)
        {
            if (!(obj is SystemUser))
            {
                return false;
            }

            SystemUser otherUser = (SystemUser)obj;

            if (this.Id.Equals(otherUser.Id) && this.Email.Equals(otherUser.Email))
            {
                return true;
            }

            return false;
        }
    }
}
